﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Web.DynamicData;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using NotAClue.ComponentModel.DataAnnotations;
using NotAClue.Web;
using System.Web;

namespace NotAClue.Web.DynamicData
{
    public static class FieldTemplateExtensionMethods
    {
        #region Static
        public static String RequiredCssClass { get; set; }
        static FieldTemplateExtensionMethods()
        {
            RequiredCssClass = "DDRequired";
        }
        #endregion

        /// <summary>
        /// Applies the CSS class to the current field template.
        /// </summary>
        /// <param name="control">The control.</param>
        /// <param name="Column">The column.</param>
        public static void ApplyCss(this FieldTemplateUserControl control)
        {
            var parentCell = control.GetContainerControl<DataControlFieldCell>();

            var cellCss = control.Column.GetAttribute<CellCssAttribute>();
            if (cellCss != null && parentCell != null)
            {
                var cssClass = parentCell.Attributes["class"];
                if (cssClass != null)
                    cssClass += " " + cellCss.Class;
                else
                    parentCell.Attributes.Add("class", cellCss.Class);
            }

            //var fieldCss = control.Column.GetAttribute<FieldCssAttribute>();
            //if (fieldCss != null && control.DataControl is Literal)
            //{
            //    ((Literal)control.DataControl).Text = String.Format("<span class=\"{0}\">{1}</span>", fieldCss.Class, ((Literal)control.DataControl).Text);
            //}
        }

        /// <summary>
        /// Populates the list control filtered attribute in meta data.
        /// </summary>
        /// <param name="fieldTemplate">The field template.</param>
        /// <param name="listControl">The list control.</param>
        /// <remarks></remarks>
        public static void PopulateListControlFiltered(this FieldTemplateUserControl fieldTemplate, ListControl listControl)
        {
            var parentTable = fieldTemplate.ForeignKeyColumn.ParentTable;
            var items = parentTable.GetQuery().ApplyColumnFilter(fieldTemplate.ForeignKeyColumn.ParentTable);
            foreach (object obj2 in items)
            {
                string displayString = parentTable.GetDisplayString(obj2);
                string primaryKeyString = parentTable.GetPrimaryKeyString(obj2);
                listControl.Items.Add(new ListItem(displayString, primaryKeyString.TrimEnd(new char[0])));
            }
        }

        /// <summary>
        /// Applies the column filter from attribute.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <param name="Table">The table.</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static IQueryable ApplyColumnFilter(this IQueryable query, MetaTable Table)
        {
            var attribute = Table.GetAttribute<FilterColumnAttribute>();
            if (attribute != null)
            {
                // do filter by column
                var filterColumn = Table.GetColumn(attribute.ColumnName);

                // get list of values filtered by the parent's selected entity
                var filteredQuery = query.GetQueryFilteredByColumn(filterColumn, attribute.Value);

                return filteredQuery;
            }

            return query;
        }

        /// <summary>
        /// Applies the column filter.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <param name="Column">The column.</param>
        /// <param name="filterValue">The filter value.</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static IQueryable ApplyColumnFilter(this IQueryable query, MetaColumn Column, String filterValue)
        {
            // get list of values filtered by the parent's selected entity
            var filteredQuery = query.GetQueryFilteredByColumn(Column, filterValue);
            return filteredQuery;
        }

        ///// <summary>
        ///// Sets the required CSS class.
        ///// </summary>
        ///// <param name="fieldTemplate">The field template.</param>
        ///// <param name="control">The control.</param>
        //public static void SetRequiredCssClass(this FieldTemplateUserControl fieldTemplate, WebControl control)
        //{
        //    if (fieldTemplate.Column.IsRequired)
        //        control.CssClass += String.Format(" {0}", RequiredCssClass);
        //}

        /// <summary>
        /// Determines whether [is navigation disabled] [the specified field template].
        /// </summary>
        /// <param name="fieldTemplate">The field template.</param>
        /// <param name="column">The column.</param>
        /// <returns>
        /// 	<c>true</c> if [is navigation disabled] [the specified field template]; otherwise, <c>false</c>.
        /// </returns>
        public static Boolean IsNavigationDisabled(this FieldTemplateUserControl fieldTemplate, MetaColumn column)
        {
            // check for Secure meta model
            if (column.Table.Model is SecureMetaModel)
            {
                var showChildrenColumn = column.GetAttributeOrDefault<ShowChildrenColumnAttribute>().ShowColumn;
                // check children column navigation is disabled
                if (column is SecureMetaChildrenColumn && !((SecureMetaModel)column.Table.Model).EnableChildrenNavigation && !showChildrenColumn)
                    return true;

                var showFkColumn = column.GetAttributeOrDefault<ShowFkColumnAttribute>().ShowColumn;
                // check foreign key column navigation is disabled
                if (column is SecureMetaForeignKeyColumn && !((SecureMetaModel)column.Table.Model).EnableForeighKeyNavigation && !showFkColumn)
                    return true;
            }

            DisableNavigationInAttribute disableNavigationIn;
            var pageTemplate = fieldTemplate.Page.GetPageTemplate();

            // get table version of attribute
            if (column is MetaForeignKeyColumn)
                disableNavigationIn = ((MetaForeignKeyColumn)column).ParentTable.GetAttribute<DisableNavigationInAttribute>();

            // get table version of attribute
            if (column is MetaChildrenColumn)
                disableNavigationIn = ((MetaChildrenColumn)column).ChildTable.GetAttribute<DisableNavigationInAttribute>();

            // get column version of attribute
            disableNavigationIn = column.GetAttribute<DisableNavigationInAttribute>();

            if (disableNavigationIn != null && (disableNavigationIn.PageTemplate & pageTemplate) == pageTemplate)
                return true;

            return false;
        }

        /// <summary>
        /// Sets the validators to image.
        /// </summary>
        /// <param name="fieldTemplate">The field template.</param>
        /// <remarks></remarks>
        public static void SetValidatorsToImage(this FieldTemplateUserControl fieldTemplate)
        {
            var errorTip = new StringBuilder();

            errorTip.Append("<span id='spanTip' class='error'>\n");
            errorTip.Append("    <img src='{0}'>\n");
            errorTip.Append("    <span class='tooltip'>\n");
            errorTip.Append("        <span class='top'></span>\n");
            errorTip.Append("            <span class='middle'><strong>Validation Error:</strong> {1}</span>\n");
            errorTip.Append("        <span class='bottom'></span>\n");
            errorTip.Append("    </span>\n");
            errorTip.Append("</span>\n");
            var validators = fieldTemplate.GetAllChildControlsRecursive<BaseValidator>();
            foreach (var v in validators)
            {
                //ErrorMessage='<img src="error.gif">'
                var ddVirtualPath = fieldTemplate.Table.Model.DynamicDataFolderVirtualPath;
                var imagePath = VirtualPathUtility.ToAbsolute(VirtualPathUtility.Combine(ddVirtualPath, "Content/Images/error.png"));
                fieldTemplate.Page.AddCssToHead(VirtualPathUtility.Combine(ddVirtualPath, "Content/ErrorBubbleToolTip.css"));
                //v.Text = String.Format("<img src='{0}' alt='{1}'>", imagePath, v.ToolTip);
                v.Text = String.Format(errorTip.ToString(), imagePath, v.ToolTip);
                v.ToolTip = String.Empty;
            }
        }

        /// <summary>
        /// Gets the default value.
        /// </summary>
        /// <param name="control">The control.</param>
        /// <param name="column">The column.</param>
        /// <returns></returns>
        public static String GetDefaultValue(this Control control, MetaColumn column)
        {
            String returnValue = String.Empty;
            if (column is MetaForeignKeyColumn)
            {
                var keys = ((MetaForeignKeyColumn)column).ForeignKeyNames.ToCsvString();
                returnValue = control.Page.Request.QueryString[keys];
            }

            if (String.IsNullOrEmpty(returnValue))
            {
                var value = column.GetAttribute<DefaultValueAttribute>();
                if (value != null)
                    returnValue = value.Value.ToString();
            }

            if (String.IsNullOrEmpty(returnValue))
                returnValue = control.Page.Request.QueryString[column.Name];

            return returnValue;
        }

        /// <summary>
        /// Sets the tip.
        /// </summary>
        /// <param name="fieldTemplate">The field template.</param>
        /// <param name="control">The associate control.</param>
        public static void SetupTip(this FieldTemplateUserControl fieldTemplate, Control control = null)
        {
            var tip = fieldTemplate.Column.GetAttribute<TipAttribute>();
            // don't show tool tip when in a List control
            if (fieldTemplate.ContainerType == ContainerType.List || tip == null)
                return;

            if (control == null)
                control = fieldTemplate.DataControl;

            var ddVirtualPath = fieldTemplate.Table.Model.DynamicDataFolderVirtualPath;

            //<span id="spanTip" class="tt" runat="server" visible="false">
            //    <asp:Image ID="Image1" ImageUrl="~/DynamicData/Content/Images/tip.png" runat="server" />
            //    <span class="tooltip">
            //        <span class="top"></span>
            //            <asp:Label ID="Label2" CssClass="middle" runat="server"></asp:Label>
            //        <span class="bottom"></span>
            //    </span>
            //</span>

            var toolTip = new HtmlGenericControl("span");
            toolTip.InnerHtml = "&nbsp;";
            toolTip.Attributes.Add("class", "tt");

            var tipImage = new Image() { ImageUrl = VirtualPathUtility.Combine(ddVirtualPath, "Content/Images/tip.png") };
            toolTip.Controls.Add(tipImage);

            var innerSpan = new HtmlGenericControl("span");
            toolTip.Controls.Add(innerSpan);

            innerSpan.Attributes.Add("class", "tooltip");
            var innerTopSpan = new HtmlGenericControl("span");
            innerTopSpan.Attributes.Add("class", "top");
            innerSpan.Controls.Add(innerTopSpan);

            var label = new Label() { CssClass = "middle" };
            innerSpan.Controls.Add(label);

            var innerBottomSpan = new HtmlGenericControl("span");
            innerBottomSpan.Attributes.Add("class", "bottom");
            innerSpan.Controls.Add(innerBottomSpan);

            if (!String.IsNullOrEmpty(tip.Title))
                label.Text = String.Format("<strong>{0}</strong><br />{1}", tip.Title, tip.Tip);
            else
                label.Text = String.Format("<strong>{0}</strong><br />{1}", fieldTemplate.Column.DisplayName, tip.Tip);

            fieldTemplate.Page.AddCssToHead(VirtualPathUtility.Combine(ddVirtualPath, "Content/BubbleToolTip.css"));

            control.AddAfter(toolTip);
        }

        /// <summary>
        /// Disables the field template.
        /// </summary>
        /// <param name="column">The column.</param>
        /// <param name="mode">The mode.</param>
        /// <param name="control">The control.</param>
        public static void DisableFieldTemplate(this MetaColumn column, DataBoundControlMode mode, WebControl control)
        {
            if (mode == DataBoundControlMode.Insert)
            {
                var insertPageTemplate = PageTemplate.Insert;
                var readOnly = column.GetAttributeOrDefault<ColumnReadOnlyInAttribute>();
                if ((readOnly.PageTemplate & insertPageTemplate) == insertPageTemplate)
                {
                    control.Enabled = false;
                    control.CssClass += " " + readOnly.DisabledCssClass;
                }
            }
        }


        /// <summary>
        /// Sets the field options.
        /// </summary>
        /// <param name="control">The control.</param>
        /// <param name="column">The column.</param>
        public static void SetFieldOptions(this FieldTemplateUserControl fieldTemplate, WebControl webControl = null)
        {
            if (webControl == null)
                webControl = (WebControl)fieldTemplate.DataControl;

            if (webControl != null)
            {
                if (fieldTemplate.Column.IsRequired)
                    webControl.SetCssClass(RequiredCssClass);

                var fieldOptions = fieldTemplate.Column.GetAttribute<FieldOptionsAttribute>();
                if (fieldOptions != null)
                {
                    if (webControl is TextBox)
                    {
                        var textBox = (TextBox)webControl;
                        textBox.TextMode = fieldOptions.TextBoxMode;

                        if (fieldOptions.Columns > 0)
                            textBox.Columns = fieldOptions.Columns;
                        if (fieldOptions.Rows > 0)
                            textBox.Rows = fieldOptions.Rows;
                    }

                    if (fieldOptions != null && fieldOptions.Width > 0)
                        webControl.Width = fieldOptions.Width;

                    if (fieldOptions != null && fieldOptions.Height > 0)
                        webControl.Width = fieldOptions.Height;
                }

                //if (webControl is TextBox)
                //{
                //    var textBox = (TextBox)webControl;
                //    if (fieldTemplate.Column.MaxLength <= 100)
                //    {
                //        textBox.Columns = fieldTemplate.Column.MaxLength;
                //    }
                //    else
                //    {
                //        textBox.TextMode = TextBoxMode.MultiLine;
                //        textBox.Columns = 80;
                //        if (fieldTemplate.Column.MaxLength <= 150)
                //            textBox.Rows = 2;
                //        else if (fieldTemplate.Column.MaxLength <= 300)
                //            textBox.Rows = 4;
                //        else if (fieldTemplate.Column.MaxLength <= 600)
                //            textBox.Rows = 8;
                //        else
                //            textBox.Rows = 10;
                //    }
                //}
                // disable control if editing is disabled.
                var editOptions = fieldTemplate.Column.GetAttributeOrDefault<DisableEditingAttribute>();
                if (editOptions.Disable)
                    webControl.Enabled = false;
            }
        }

        ///// <summary>
        ///// Sets the field options.
        ///// </summary>
        ///// <param name="control">The control.</param>
        ///// <param name="column">The column.</param>
        //public static void SetFieldOptions(this WebControl control, MetaColumn column)
        //{
        //    var fieldOptions = column.GetAttribute<FieldOptionsAttribute>();
        //    if (fieldOptions == null)
        //        return;

        //    if (control is TextBox)
        //    {
        //        var textBox = (TextBox)control;
        //        textBox.TextMode = fieldOptions.TextBoxMode;
        //        if (fieldOptions.Columns > 0)
        //            textBox.Columns = fieldOptions.Columns;
        //        if (fieldOptions.Rows > 0)
        //            textBox.Rows = fieldOptions.Rows;
        //    }

        //    if (fieldOptions != null && fieldOptions.Width > 0)
        //        control.Width = fieldOptions.Width;
        //    if (fieldOptions != null && fieldOptions.Height > 0)
        //        control.Width = fieldOptions.Height;
        //}

        /// <summary>
        /// Gets the page template.
        /// </summary>
        /// <returns></returns>
        public static PageTemplate GetPageTemplate()
        {
            var pageTemplate = PageTemplate.Unknown;
            if (System.Web.HttpContext.Current != null)
            {
                var page = System.Web.HttpContext.Current.Handler as Page;
                pageTemplate = page.GetPageTemplate();
            }

            return pageTemplate;
        }

        /// <summary>
        /// Gets the primary key values as string.
        /// </summary>
        /// <param name="table">The table.</param>
        /// <param name="page">The page.</param>
        /// <returns></returns>
        public static String GetPrimaryKeyValuesAsString(this MetaTable table, Page page)
        {
            var pkValues = new StringBuilder();
            var keys = table.PrimaryKeyColumns;
            foreach (var key in keys)
            {
                pkValues.Append(page.Request.QueryString[key.Name] + ",");
            }
            return pkValues.ToString().Substring(0, pkValues.Length - 1);
        }

        /// <summary>
        /// Gets the foreign key values as string.
        /// </summary>
        /// <param name="control">The control.</param>
        /// <param name="table">The table.</param>
        /// <param name="fkColumnName">Name of the foreign key column.</param>
        /// <returns></returns>
        public static String GetForiegnKeyValuesAsString(this Control control, MetaTable table, String fkColumnName)
        {
            var foreignKeyColumn = table.GetColumn(fkColumnName) as MetaForeignKeyColumn;
            if (foreignKeyColumn == null)
                return null;

            var fkValues = new StringBuilder();
            var listView = control.GetParent<ListView>();
            if (listView != null)
            {
                // in DetailsList page set default 
                // value based on where parameters
                var dataSource = listView.DataSourceObject as IDynamicDataSource;
                foreach (Parameter p in dataSource.WhereParameters)
                {
                    if (foreignKeyColumn.ForeignKeyNames.Contains(p.Name))
                        fkValues.Append(p.DefaultValue + ",");
                }
            }
            if (fkValues.Length > 0)
                return fkValues.ToString().Substring(0, fkValues.Length - 1);
            else
                return null;
        }

        /// <summary>
        /// Gets the default value.
        /// </summary>
        /// <param name="fieldTemplate">The field template.</param>
        /// <returns></returns>
        public static String GetDefaultValue(this FieldTemplateUserControl fieldTemplate)
        {
            String returnValue = String.Empty;
            if (fieldTemplate.Column is MetaForeignKeyColumn)
            {
                var keys = ((MetaForeignKeyColumn)fieldTemplate.Column).ForeignKeyNames.ToCsvString();
                returnValue = fieldTemplate.Page.Request.QueryString[keys];
            }

            if (String.IsNullOrEmpty(returnValue))
            {
                var value = fieldTemplate.Column.GetAttribute<DefaultValueAttribute>();
                if (value != null)
                    returnValue = value.Value.ToString();
            }

            if (String.IsNullOrEmpty(returnValue))
                returnValue = fieldTemplate.Page.Request.QueryString[fieldTemplate.Column.Name];

            return returnValue;
        }
    }
}
